#include <iostream>
#include <algorithm>
#include <memory>
#include <string>
#include <sstream>
using namespace std;
#include "User.h"

User::User(const int& id, const string& name, const string& password, PB_t permissionBits, const string& roleDescription) :
    id(id), name(name), password(password), permissionBits(permissionBits), roleDescription(roleDescription) {
}
User::~User() {}

int User::getId() const { return this->id; }
string User::getName()const { return this->name; }
string User::getPassword()const { return this->password; }
PB_t User::getPermissionBits()const { return this->permissionBits; }
Role User::getRole()const { return this->role; }
string User::getRoleDescription()const { return this->roleDescription; }

void User::setPermissionBits(PB_t permissionBits) { this->permissionBits = permissionBits; }
void User::setRole(Role role) { this->role = role; }

int User::check_permission(UPBits pb) { cout << "正在进行USER权限校验" << endl;return 0; }
void User::change_password(const string& newPassword) { this->password = newPassword; }


string User::serialize(void)
{
    return to_string(id) + "|" + name + "|" + password + "|" + to_string(permissionBits) + "|" + to_string((int)role) + "|" + roleDescription + "\n";
}

int User::deSerialize(const string& str)
{
    istringstream iss(str);
    string token;
    getline(iss, token, '|');
    id = stoi(token);
    getline(iss, token, '|');
    name = token;
    getline(iss, token, '|');
    password = token;
    getline(iss, token, '|');
    permissionBits = stoi(token);
    getline(iss, token, '|');
    role = (Role)stoi(token);
    getline(iss, token, '|');
    roleDescription = token;
    return 0;
}

/*============================================<管理员类实现>============================================*/
Admin::Admin(const int& id, const string& name, const string& password, PB_t permissionBits, const string& roleDescription) :
    User(id, name, password, permissionBits, roleDescription) {}
Admin::Admin(const User& user) :User(user) {}
Admin::~Admin() {}


int Admin::add_user(vector<MYPTR_T>& userLib,User& user, Role role)
{
    MYPTR_T newUser = nullptr;
    // User* newUser = nullptr;
    switch (role)
    {
        case Role::ADMIN:
            newUser = make_shared<Admin>(user);
            break;
        case Role::USER_INFO:
            newUser = make_shared<User>(user);
            break;
        case Role::USER_STORE_CHECK:
            newUser =  make_shared<User>(user);
            break;
        case Role::USER_STORE_IO:
            newUser = make_shared<User>(user);
            break;
        default:
            break;
    }
    
    if (newUser != nullptr)
    {
        newUser->setRole(role);
        userLib.push_back(newUser);
        return 0;
    }
    else
    {
        return -1;
    }
        
}

int Admin::delete_user(vector<MYPTR_T>& userLib, int id)
{
    auto it = find_if(userLib.begin(), userLib.end(), [id](MYPTR_T user) {return user->getId() == id; });
    if (it == userLib.end())
        return -1;

    userLib.erase(it);
    return 0;
}

int Admin::modify_user(vector<MYPTR_T>& userLib, int id, const User& user)
{
    auto it = find_if(userLib.begin(), userLib.end(), [id](MYPTR_T user) {return user->getId() == id; });
    if (it == userLib.end())
        return -1;
    
    PB_t tmp = (*it)->getPermissionBits();
    Role tempRole = (*it)->getRole();
    MYPTR_T tempClass = make_shared<User>(user);
    (*it) = tempClass;
    (*it)->setPermissionBits(tmp);
    (*it)->setRole(tempRole);
    return 0;
  
}

MYPTR_T Admin::find_user(vector<MYPTR_T>& userLib, int id)
{
    auto it = find_if(userLib.begin(), userLib.end(), [id](MYPTR_T user) {return user->getId() == id; });
    if (it == userLib.end())
        return nullptr;
    return *it;
}


int Admin::modify_user_permission(vector<MYPTR_T>& userLib, int id, PB_t permissionBits)
{
    auto it = find_if(userLib.begin(), userLib.end(), [id](MYPTR_T user) {return user->getId() == id; });
    if (it == userLib.end())
        return -1;
    
    (*it)->setPermissionBits(permissionBits);
    return 0;
}


int Admin::check_permission(UPBits pb)
{
    cout << "正在进行管理员身份权限校验..." << endl;
    if ((this->permissionBits & (PB_t)pb) == (PB_t)pb)
    {
        cout << "权限校验成功" << endl;
        return 0;
    }

    return -1; 
}

/*============================================<信息配置人员类实现>============================================*/
User_info::User_info(const int& id, const string& name, const string& password, PB_t permissionBits, const string& roleDescription) :
    User(id, name, password, permissionBits, roleDescription) {
}
User_info::User_info(const User& user) :User(user) {}
User_info::~User_info() {}


int User_info::check_permission(UPBits pb)
{
    cout << "正在进行配件信息录入人员身份权限校验..." << endl;
    if ((this->permissionBits & (PB_t)pb) == (PB_t)pb)
    {
        cout << "权限校验成功" << endl;
        return 0;
    }

    return -1; 
}

/*============================================<仓库管理人员类实现>============================================*/
User_storeIO::User_storeIO(const int& id, const string& name, const string& password, PB_t permissionBits, const string& roleDescription) :
    User(id, name, password, permissionBits, roleDescription) {}
User_storeIO::User_storeIO(const User& user):User(user) {}
User_storeIO::~User_storeIO() {}

int User_storeIO::check_permission(UPBits pb)
{
    cout << "正在进行仓库管理人员身份权限校验..." << endl;
    if ((this->permissionBits & (PB_t)pb) == (PB_t)pb)
    {
        cout << "权限校验成功" << endl;
        return 0;
    }
 
    return -1; 
}


/*=============================<仓库盘点人员类实现>=============================*/
User_storeCheck::User_storeCheck(const int& id, const string& name, const string& password, PB_t permissionBits, const string& roleDescription) :
    User(id, name, password, permissionBits, roleDescription) {}
User_storeCheck::User_storeCheck(const User& user) :User(user) {}
User_storeCheck::~User_storeCheck() {}


int User_storeCheck::check_permission(UPBits pb)
{
    cout << "正在进行仓库盘点人员身份权限校验..." << endl;
    if ((this->permissionBits & (PB_t)pb) == (PB_t)pb)
    {
        cout << "权限校验成功" << endl;
        return 0;
    }
    return -1; 
}
